import { contextBridge, ipcRenderer } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'
import { OpenDialogOptions } from 'electron'
import type { IProcessOptions, IProcessResult } from './index.d'

const dialogApi = {
  showOpenDialog: (options: OpenDialogOptions) => ipcRenderer.invoke('dialog.showOpenDialog', options)
}

const childProcessApi = {
  exec: (command: string, options?: IProcessOptions) => ipcRenderer.invoke('childProcess.exec', command, options),
  spawn: (command: string, args: string[], options?: IProcessOptions) => ipcRenderer.invoke('childProcess.spawn', command, args, options),
  getEnv: () => ipcRenderer.invoke('childProcess.getEnv'),
  onOutput: (callback: (data: { type: 'stdout' | 'stderr'; data: string }) => void) => {
    ipcRenderer.on('childProcess.output', (_, data) => callback(data))
  },
  offOutput: () => {
    ipcRenderer.removeAllListeners('childProcess.output')
  }
}

const fsApi = {
  existsSync: (path: string) => ipcRenderer.invoke('fs.existsSync', path),
  productPath: () => ipcRenderer.invoke('fs.productPath'),
  mkdir: (path: string) => ipcRenderer.invoke('fs.mkdir', path),
  writeFile: (path: string, data: string) => ipcRenderer.invoke('fs.writeFile', path, data),
  unlink: (path: string) => ipcRenderer.invoke('fs.unlink', path),
  rmdir: (path: string) => ipcRenderer.invoke('fs.rmdir', path),
  readFile: (path: string) => ipcRenderer.invoke('fs.readFile', path)
}

const pathApi = {
  join: (...paths: string[]) => ipcRenderer.invoke('path.join', ...paths)
}

const windowApi = {
  close: () => ipcRenderer.send('window.close'),
  openConsole: () => ipcRenderer.send('window.openConsole')
}

const dbApi = {
  get: (sql: string, ...params: any[]) => ipcRenderer.invoke('db.get', sql, ...params),
  all: (sql: string, ...params: any[]) => ipcRenderer.invoke('db.all', sql, ...params),
  run: (sql: string, ...params: any[]) => ipcRenderer.invoke('db.run', sql, ...params)
}

const platformApi = {
  isWindows: process.platform === 'win32',
  isMac: process.platform === 'darwin',
  isLinux: process.platform === 'linux'
}

if (process.contextIsolated) {
  try {
    contextBridge.exposeInMainWorld('electron', electronAPI)
    contextBridge.exposeInMainWorld('dialog', dialogApi)
    contextBridge.exposeInMainWorld('childProcess', childProcessApi)
    contextBridge.exposeInMainWorld('fs', fsApi)
    contextBridge.exposeInMainWorld('path', pathApi)
    contextBridge.exposeInMainWorld('db', dbApi)
    contextBridge.exposeInMainWorld('windowApi', windowApi)
    contextBridge.exposeInMainWorld('platform', platformApi)
  } catch (error) {
    console.error(error)
  }
} else {
  // @ts-ignore (define in dts)
  window.electron = electronAPI
  // @ts-ignore (define in dts)
  window.dialog = dialogApi
  // @ts-ignore (define in dts)
  window.childProcess = childProcessApi
  // @ts-ignore (define in dts)
  window.fs = fsApi
  // @ts-ignore (define in dts)
  window.path = pathApi
  // @ts-ignore (define in dts)
  window.db = dbApi
  // @ts-ignore (define in dts)
  window.windowApi = windowApi
  // @ts-ignore (define in dts)
  window.platform = platformApi
}
